A virtual machine (VM) environment executes programs in a manner which is generally independent of the underlying complexities in the platform used to implement the execution. Microsoft Corporation's .NET Framework (provided by Microsoft Corporation of Redmond, Wash.) provides a virtual machine environment with its Common Language Runtime (CLR) functionality. Sun's Java (provided by Sun Microsystems, Inc. of Santa Clara, Calif.) provides another well known virtual machine environment.
FIG. 1 shows an overview of the operation of an exemplary architecture 100 employed by the .NET Framework in generating and executing code. Broadly stated, the architecture 100 performs a series of actions 102 used to generate intermediate language (IL) code, and another series of actions 104 for loading and executing that intermediate language code in a specific computing platform.
To begin with, source code 106 (such as program “Application.cs”) is fed to a compiler 108. The source code can be written in a variety of languages that target the .NET Framework, such as C#, Visual Basic.NET, JScript.NET, C++ with Managed Extensions, and so on. The architecture 100 can use different kinds of compilers depending on the language used to create the source code 106. For instance, FIG. 1 shows the exemplary use of a C# compiler 108 to transform a source program written in C#.
The compiler 108 produces the intermediate language (IL) code and metadata 110. This IL is expressed in a common coding framework regardless of the language that was used to create the original source code 106. Metadata provides descriptive information regarding the IL. In general, the common coding framework provided by the IL and the metadata 110 are specifically tailored to make use of the common resources of the .NET Framework environment, and, in particular, to make use of the CLR. Code that is built to utilize the CLR is referred to as “managed code.”
A key feature provided by the CLR is its use of a common set of programming types via a Common Type System (CTS). Generally, a type pertains to rules used to interpret information in the source code. CTS specifies a variety of types, including classes, interfaces, arrays, delegates, etc. A class refers to a collection that can include methods, properties, and events. An interface also refers to a collection that can include methods, properties, and events; interfaces differ from classes in that they specify software contracts, without implementation. An array refers to a collection of values having the same type. A delegate refers to a link to a method. The above-mentioned metadata generated by the compiler 108 provides descriptive information pertaining to these types, such as the name of the type, the identity of any interfaces which the type references, the identity of any methods implemented by the types, and so on. Additional information regarding the basics of the .NET Framework can be found in a number of introductory texts, such as Pratt, Introducing Microsoft .NET, Third Edition, Microsoft Press, 2003.
In the execution phase 104, the architecture 100 uses a CLR loader and a just-in-time (JIT) compiler (generally illustrated in FIG. 1 as a “loader/JIT” component 112) to transform the IL and metadata 110 into native code 114. More specifically, the loader/JIT component 112 provides code access security, cross-language integration, debugging, object lifetime management, and so on. The native code 114 constitutes the actual machine code that will run on an execution platform (e.g., a specific computing machine). The compilation process provided by the loader/JIT component 112 is referred to as “just-in-time” because the compilation can take place just prior to the execution of the code.
The architecture 100 performs the above-identified tasks in the context of units of code referred to as “assemblies.” An assembly refers to a collection of one or more files that are versioned, security coded, and deployed as a unit. An assembly manifest provides assembly metadata that describes various characteristics of the assembly files, and which effectively ties these assembly files together. One piece of metadata contained within the assembly manifest is an indication of whether the resources contained within the assembly are marked as non-public resources or public resources. Resources of an assembly that are designated as non-public resources are only “visible” to “entities” within the defining assembly, such as by methods contained within the defining assembly. On the other hand, resources of an assembly that are designated as public are visible to entities both within and outside the defining assembly, such as methods provided in another assembly. During execution of an assembly that references another assembly's resources, the loader/JIT component 112 reads the metadata of that other assembly to determine whether these resources are public; if so, then execution can proceed, and if not, execution cannot proceed.
FIG. 2 broadly illustrates the above-described concepts in an exemplary scenario 200. The scenario 200 shows four compiled assemblies, including assembly A 202, assembly B 204, assembly C 206, and assembly D 208. In this exemplary case, assembly A 202 includes public resources 210 that are visible to other assemblies (such as assembly B 204, assembly C 206, and assembly D 208). Assembly A 202 also includes non-public resources 212 that are not visible to other assemblies (e.g., assembly B 204, assembly C 206, and assembly D 208). These public and non-public resources (210, 212) can correspond to classes or other types within assembly A 202. FIG. 2 illustrates the above-identified concepts by showing an arrow without an “X” that points from assemblies B, C, and D (204, 206, 208) to the public resources 210, and an arrow with an “X” that points from assemblies B, C, and D (204, 206, 208) to the non-public resources 212. That is, the arrow without the “X” indicates that visibility is permitted, and the arrow with the “X” indicates that visibility is precluded (or blocked).
By virtue of the above-described designation of resources as public and non-public, the loader/JIT component 112 will not allow any “outside” assembly (such as assembly B 204, assembly C 206, and assembly D 208) to access assembly A 202's non-public resources 212. Thus, designating the resources 212 as non-public serves a security role by preventing other assemblies from tampering with potentially private and sensitive information provided by the assembly A 202.
Nevertheless, there is a price to pay for the above-mentioned security benefits. Namely, some of the outside assemblies may have a legitimate (e.g., non-malicious) need to access the non-public resources 212 of assembly A 202, but the non-public status of these resources 212 prevents these outside assemblies from accessing these resources 212. One way to address this problem is to re-designate the non-public resources 212 as public resources. This opens up the previously non-public resources 212 to all legitimate uses by outside assemblies; however, the public designation is not discriminatory, so that it also accommodates assemblies that wish to access the resources 212 for non-legitimate (e.g., malicious) uses. This can result in a security breach and potential corruption of computer code and database records. Further, even where there is no security risk involved in providing assembly resources to a wider population of outside assemblies, the designer of the assembly may nonetheless wish to restrict the population of interacting assemblies so as to simplify the assembly's design and testing; that is, an assembly may need to adopt a more robust design if it is intended to interact with a wider population of assemblies than originally intended.
Another way to permit an outside assembly to access the non-public resources 212 of assembly A 202 is to redesign that outside assembly such that it actually incorporates all of the resources that its needs from assembly A 202. However, this change is typically a relatively invasive, error prone, and time intensive task, requiring redesign of source code, recompiling, and so on. Also, this solution reduces the modularity and independence of a software product's computer code, which is generally considered a negative consequence in the computing arts.
Accordingly, there is an exemplary need in the art to provide a more efficient way of permitting an entity to selectively gain access to resources in an assembly that have been designated as non-public.